from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from django import http
from random import randint

from meiduo_mall.libs.captcha.captcha import captcha
from meiduo_mall.utils.response_code import RETCODE
# from meiduo_mall.libs.yuntongxun.sms import CCP
from celery_tasks.sms.tasks import send_sms_code
from . import constans
# 谁发的请求,谁接响应
import logging
logger = logging.getLogger('django')


class ImageCodeView(View):
    """图形验证码"""
    def get(self, request, uuid):
        # 1. 调用图形验证码SDK 生成图形验证码数据
        # name: 随机唯一标识
        # image_str: 图形验证码字符串
        # image_code_bytes: 图形验证码图片bytes
        name, image_str, image_code_bytes = captcha.generate_captcha()

        # 2. 创建redis连接对象
        redis_cli = get_redis_connection('verify_codes')

        # 3. 存储string类型 {uuid: 图形验证码字符}
        # redis_cli.setex(key, 过期时间, value)
        # 存储图形验证码目的是为了后面发短信时,比对图形验证码是否填写正确
        redis_cli.setex(uuid, constans.IMAGE_CODE_REDIS_EXPIRES, image_str)

        # 4. 将图形验证码数据响应
        return http.HttpResponse(image_code_bytes, content_type='image/jpeg')


class SMSCodeView(View):
    """短信验证码"""
    def get(self, request, mobile):

        # 创建redis连接对象
        redis_cli = get_redis_connection('verify_codes')
        # 0.先尝试获取此手机号发送短信标识
        send_flag = redis_cli.get('send_flag_%s' % mobile)
        # 0.1 如果有短信标识,提交响应
        if send_flag:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '请不要频繁发送,要收费啊!'})

        # 1. 接收
        query_dict = request.GET
        image_code_client = query_dict.get('image_code')
        uuid = query_dict.get('uuid')

        # 2. 校验
        if all([image_code_client, uuid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        # 2.2 获取redis中指定uuid 对应的图形验证码
        image_code_server_bytes = redis_cli.get(uuid)
        # 2.2.1 让图形验证码只能比对一次
        redis_cli.delete(uuid)

        # 2.3 判断图形验证码是否已过期
        if image_code_server_bytes is None:
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已过期'})
        # 2.3.1 将bytes类型转换为字符串(在django从redis获取出来的数据默认是bytes类型)
        image_code_server = image_code_server_bytes.decode()
        # 2.4 判断用户填写的和服务器取出的图形验证码是否一致
        if image_code_client.lower() != image_code_server.lower():
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码填写错误'})

        # 3. 处理业务逻辑
        # 3.1 生成随机6位数字,
        sms_code = '%06d' % randint(0, 999999)
        logger.info(sms_code)

        # 3.2 发短信SDK 第三方(容联云)
        # CCP().send_template_sms(to='接收验证码的手机号', datas=['短信验证码', '提示用户多少分钟过期'], temp_id=1)
        # CCP().send_template_sms(to=mobile, datas=[sms_code, constans.SMS_CODE_REDIS_EXPIRES // 60], temp_id=1)
        # send_sms_code(mobile, sms_code)  # 如果直接调用celery异步任务默认还是在当前线程执行
        send_sms_code.delay(mobile, sms_code)  # 当执行到此行代码时,只是触发异步任务,celery客户端将此任务添加到任务队列
        # 3.2.1 创建管道对象
        pl = redis_cli.pipeline()

        # 3.3 将短信验证码存储到redis,以备注册时校验用户短信验证码是否填写正确
        # redis_cli.setex('sms_%s' % mobile, constans.SMS_CODE_REDIS_EXPIRES, sms_code)  # 用常量替换魔法数字
        pl.setex('sms_%s' % mobile, constans.SMS_CODE_REDIS_EXPIRES, sms_code)  # 用常量替换魔法数字

        # 存储此手机号已发送过短信的标识 60s
        # redis_cli.setex('send_flag_%s' % mobile, constans.SEND_FLAG_REDIS_EXPIRES, 1)
        pl.setex('send_flag_%s' % mobile, constans.SEND_FLAG_REDIS_EXPIRES, 1)

        # 管道必须要去执行
        pl.execute()

        # 4. 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})